package com.fc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fc.dao.UserMapper;
import com.fc.entity.Product;
import com.fc.entity.User;
import com.fc.entity.input.DeleteBatchInput;
import com.fc.entity.input.UserInput;
import com.fc.entity.input.UserQueryInput;
import com.fc.entity.query.PageQuery;
import com.fc.enums.DelFlagEnum;
import com.fc.exception.BusinessException;
import com.fc.service.UserService;
import com.fc.service.baseService.impl.BaseServiceImpl;
import com.fc.utils.ParseWrapper;
import com.fc.utils.ResultVO;
import org.apache.commons.codec.binary.Hex;
import org.springframework.stereotype.Service;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author
 * @since 2024-10-31
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implements UserService {

    /**
     * 新增
     */
    @Override
    public boolean add(UserInput input) {
        input.setId(null);
        check(input);
        changeMD5(input);
        return savePre(BeanUtil.copyProperties(input, User.class));
    }

    /**
     * 分页模糊查询
     */
    @Override
    public IPage<User> getPage(PageQuery query, UserQueryInput input) {
        QueryWrapper<User> wrapper = ParseWrapper.parseWrap(input, User.class);
        wrapper.lambda().eq(User::getDelFlag, DelFlagEnum.NORMAL);
        return page(Page.of(query.getPageNumber(), query.getPageSize()), wrapper);
    }

    /**
     * 修改
     */
    @Override
    public boolean renew(UserInput input) {
        User user = getById(input.getId());
        if (user == null || user.getDelFlag().equals(DelFlagEnum.DELETED)) {
            throw new BusinessException(9999, "用户不存在");
        }
        check(input);
        changeMD5(input);
        return updateByIdPre(BeanUtil.copyProperties(input, User.class));
    }

    @Override
    public boolean del(DeleteBatchInput input) {
        List<User> categories = listByIds(input.getIds());
        if (categories == null || categories.size() != input.getIds().size()) {
            throw new BusinessException(9999, "部分id不存在");
        }
        List<User> list = input.getIds().stream().map(i -> {
            User user = new User();
            user.setId(i);
            user.setDelFlag(DelFlagEnum.DELETED);
            return user;
        }).toList();
        return updateBatchByIdPre(list);
    }

    /**
     * 查询详情
     */
    @Override
    public ResultVO<User> detail(Long id) {
        User user = getById(id);
        if (Objects.isNull(user) || user.getDelFlag().equals(DelFlagEnum.DELETED)) {
            throw new BusinessException(9999, "用户不存在");
        }
        return ResultVO.success(user);
    }

    @Override
    public User getUserByName(String userName) {
        return getOne(new LambdaQueryWrapper<User>()
                .eq(User::getDelFlag, DelFlagEnum.NORMAL)
                .eq(User::getUsername, userName));
    }

    private void check(UserInput input) {
        List<User> list = list(new LambdaQueryWrapper<User>()
                .eq(User::getDelFlag, DelFlagEnum.NORMAL)
                .eq(User::getUsername, input.getUsername())
                .ne(input.getId() != null, User::getId, input.getId()));
        if (CollUtil.isNotEmpty(list)) {
            throw new BusinessException(9999, "用户名已存在");
        }
    }

    private void changeMD5(UserInput input) {
        try {
            // 获取 MD5 消息摘要算法的实例
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 计算消息摘要
            byte[] digest = md.digest(input.getPassword().getBytes());
            // 将字节数组转换为十六进制字符串
            String hexString = Hex.encodeHexString(digest);
            input.setPassword(hexString);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5 algorithm not found", e);
        }
    }
}
